package com.cardone.persistent.builder;

import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Map;

import lombok.Getter;
import lombok.Setter;
import lombok.experimental.Accessors;

import org.apache.commons.lang3.ArrayUtils;
import org.springframework.data.annotation.Transient;
import org.springframework.util.CollectionUtils;

import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
 * 对象参数
 *
 * @author yaohaitao
 */
@Getter
@Setter
@Accessors(chain = true)
public class ModelArgs implements java.io.Serializable {
	/**
	 * 序列号
	 */
	private static final long serialVersionUID = -6258631484971104514L;

	/**
	 * 类型
	 */
	private Class<?> c;

	/**
	 * 忽略Annotation类型集合
	 */
	private List<Class<? extends Annotation>> ignoreAnnotationClassList;

	/**
	 * 忽略属性数组
	 */
	private String[] ignoreProperties;

	private Boolean isSimple;

	/**
	 * 键基本名称
	 */
	private String[] keyBases;

	/**
	 * 键前缀名称
	 */
	private String keyPrefix;

	/**
	 * 键后缀名称
	 */
	private String keySuffix;

	/**
	 * 键值映射
	 */
	private Map<String, Object> kvMap;

	/**
	 * 对象
	 */
	private Object o;

	/**
	 * 跳过空值
	 */
	private Boolean skipNullValue;

	/**
	 * 使用Annotation类型集合
	 */
	private List<Class<? extends Annotation>> useAnnotationClassList;

	/**
	 * 使用属性数组
	 */
	private String[] useProperties;

	/**
	 * 值
	 */
	private Object value;

	/**
	 * 对象参数
	 *
	 * @param c
	 *          类型
	 */
	public ModelArgs(final Class<?> c) {
		this.c = c;
	}

	/**
	 * 对象参数
	 *
	 * @param o
	 *          对象
	 */
	public ModelArgs(final Object o) {
		this.o = o;
	}

	/**
	 * 对象参数
	 *
	 * @param o
	 *          对象
	 * @param c
	 *          类型
	 */
	public ModelArgs(final Object o, final Class<?> c) {
		this.o = o;
		this.c = c;
	}

	/**
	 * 对象参数
	 *
	 * @param o
	 *          对象
	 * @param useProperties
	 *          使用属性数组
	 */
	public ModelArgs(final Object o, final String... useProperties) {
		this.o = o;
		this.useProperties = useProperties;
	}

	/**
	 * 对象参数
	 *
	 * @param keyPrefix
	 *          键前缀名称
	 */
	public ModelArgs(final String keyPrefix) {
		this.keyPrefix = keyPrefix;
	}

	/**
	 * 对象参数
	 *
	 * @param keyPrefix
	 *          键前缀名称
	 * @param o
	 *          对象
	 * @param useProperties
	 *          使用属性数组
	 */
	public ModelArgs(final String keyPrefix, final Object o, final String... useProperties) {
		this.keyPrefix = keyPrefix;
		this.o = o;
		this.useProperties = useProperties;
	}

	/**
	 * 添加
	 *
	 * @param ignoreAnnotationClass
	 *          忽略Annotation
	 * @return 对象参数
	 */
	public ModelArgs addIgnoreAnnotationClassList(final Class<? extends Annotation> ignoreAnnotationClass) {
		if (CollectionUtils.isEmpty(this.ignoreAnnotationClassList)) {
			this.ignoreAnnotationClassList = Lists.newArrayList();

			this.ignoreAnnotationClassList.add(Transient.class);
		}

		if (!this.ignoreAnnotationClassList.contains(ignoreAnnotationClass)) {
			this.ignoreAnnotationClassList.add(ignoreAnnotationClass);
		}

		return this;
	}

	/**
	 * 添加
	 *
	 * @param useAnnotationClass
	 *          使用Annotation
	 * @return 对象参数
	 */
	public ModelArgs addUseAnnotationClassList(final Class<? extends Annotation> useAnnotationClass) {
		if (CollectionUtils.isEmpty(this.useAnnotationClassList)) {
			this.useAnnotationClassList = Lists.newArrayList();
		}

		this.useAnnotationClassList.add(useAnnotationClass);

		return this;
	}

	/**
	 * 获取
	 *
	 * @return 忽略Annotation类型集合
	 */
	public List<Class<? extends Annotation>> getIgnoreAnnotationClassList() {
		if (CollectionUtils.isEmpty(this.ignoreAnnotationClassList)) {
			this.ignoreAnnotationClassList = Lists.newArrayList();

			this.ignoreAnnotationClassList.add(Transient.class);
		}

		return this.ignoreAnnotationClassList;
	}

	/**
	 * 获取
	 *
	 * @return 忽略属性数组
	 */
	public String[] getIgnoreProperties() {
		if (ArrayUtils.isEmpty(this.ignoreProperties)) {
			this.ignoreProperties = new String[] { Model.Keys.serialVersionUID.stringValue() };
		}

		return this.ignoreProperties;
	}

	/**
	 * 设置：键值对
	 *
	 * @param k
	 *          键
	 * @param v
	 *          值
	 * @return 对象参数
	 */
	public ModelArgs putKvMap(final String k, final Object v) {
		if (CollectionUtils.isEmpty(this.kvMap)) {
			this.kvMap = Maps.newHashMap();
		}

		this.kvMap.put(k, v);

		return this;
	}
}
